package cn.ren.cloud.service.impl;

import cn.ren.cloud.domain.Course;
import cn.ren.cloud.domain.CourseMarket;
import cn.ren.cloud.domain.CourseOrder;
import cn.ren.cloud.domain.CourseOrderItem;
import cn.ren.cloud.dto.CourseOrderExtParamsDto;
import cn.ren.cloud.dto.CourseOrderPayDto;
import cn.ren.cloud.dto.OrderCourserDto;
import cn.ren.cloud.enums.GlobelExceptionEnum;
import cn.ren.cloud.feign.CourseFeignClient;
import cn.ren.cloud.mapper.CourseOrderMapper;
import cn.ren.cloud.result.JsonResult;
import cn.ren.cloud.service.ICourseOrderItemService;
import cn.ren.cloud.service.ICourseOrderService;
import cn.ren.cloud.utils.AssertUtil;
import cn.ren.cloud.utils.CodeGenerateUtils;
import cn.ren.cloud.vo.CourseInfoVo;
import cn.ren.cloud.vo.CourseOrderVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Ren
 * @since 2023-01-09
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    private final RedisTemplate<Object, Object> redisTemplate;
    private final CourseFeignClient courseFeignClient;
    private final ICourseOrderItemService courseOrderItemService;
    private final RocketMQTemplate rocketMQTemplate;

    public CourseOrderServiceImpl(RedisTemplate<Object, Object> redisTemplate, CourseFeignClient courseFeignClient, ICourseOrderItemService courseOrderItemService, RocketMQTemplate rocketMQTemplate) {
        this.redisTemplate = redisTemplate;
        this.courseFeignClient = courseFeignClient;
        this.courseOrderItemService = courseOrderItemService;
        this.rocketMQTemplate = rocketMQTemplate;
    }

    /**
     * 下单
     *
     * @param courserDto 封装参数
     */
    @Override
    public String placeOrder(OrderCourserDto courserDto) {
        // 获取VO数据
        List<Long> courseIds = courserDto.getCourseIds();
        String token = courserDto.getToken();
        Integer payType = courserDto.getPayType();
        // 效验token是否有效
        Long loginId = 1L;
        // 分割IDS
        String idsStr = courseIds.stream().map(String::valueOf).collect(Collectors.joining(","));
        String key = loginId + ":" + idsStr;
        // 获取redis中key
        Object redisToken = redisTemplate.opsForValue().get(key);
        // 断言redis中token是否为空，与前端token做对比是否相等
        AssertUtil.isNotNull(redisToken, GlobelExceptionEnum.ORDER_REDIS_TOKEN_IS_NULL);
        AssertUtil.isEquals(redisToken.toString(), token, GlobelExceptionEnum.ORDER_TOKEN_NOT_EQUAL);
        // 删除token
        redisTemplate.delete(key);
        // 根据ID查询课程信息和总价
        JsonResult info = courseFeignClient.getInfo(idsStr);
        // 断言课程信息是否有值
        AssertUtil.isTrue(info.isSuccess(), GlobelExceptionEnum.GLOBE_EXCEPTION_ENUM_PARAM_ERROR);
        AssertUtil.isNotNull(info.getData(), GlobelExceptionEnum.GLOBE_EXCEPTION_ENUM_PARAM_ERROR);
        // 把课程信息添加到CourseOrderVo中
        CourseOrderVo courseOrderVo = JSON.parseObject(JSON.toJSONString(info.getData()), CourseOrderVo.class);
        // 获取出课程详细信息
        List<CourseInfoVo> courseInfos = courseOrderVo.getCourseInfos();
        // 获取总价
        BigDecimal totalAmount = courseOrderVo.getTotalAmount();
        // 新建时间
        Date date = new Date();
        // 使用工具类随机生成订单号
        String orderNo = CodeGenerateUtils.generateOrderSn(loginId);
        // 对主订单进行数据添加
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setOrderNo(orderNo);
        courseOrder.setCreateTime(date);
        courseOrder.setTotalAmount(totalAmount);
        courseOrder.setStatusOrder(CourseOrder.WAIT_PAY);
        courseOrder.setUserId(loginId);
        courseOrder.setTotalCount(courseIds.size());
        courseOrder.setPayType(payType);
        courseOrder.setVersion(0);
        String titleTmp = "购买课程 [%s] , 支付[%s] 元";
        String courseName = courseInfos.stream().map(e -> e.getCourse().getName()).collect(Collectors.joining(";"));
        String format = String.format(titleTmp, courseName, totalAmount);
        courseOrder.setTitle(format);
        // 对快照订单进行数据添加
        courseInfos.forEach(e -> {
            Course course = e.getCourse();
            CourseMarket courseMarket = e.getCourseMarket();
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            courseOrderItem.setCourseId(course.getId());
            courseOrderItem.setAmount(courseMarket.getPrice());
            courseOrderItem.setCreateTime(date);
            courseOrderItem.setOrderNo(orderNo);
            courseOrderItem.setCourseName(courseName);
            courseOrderItem.setCount(1);
            courseOrderItem.setVersion(0);
            courseOrderItem.setCoursePic(course.getPic());
            courseOrder.getCourseOrderItems().add(courseOrderItem);
        });
        // 事务消息
        CourseOrderPayDto courseOrderPayDto = new CourseOrderPayDto();
        BeanUtils.copyProperties(courseOrder, courseOrderPayDto);
        // 设置扩展参数
        CourseOrderExtParamsDto courseOrderExtParamsDto = new CourseOrderExtParamsDto();
        courseOrderExtParamsDto.setOrderNo(orderNo);
        courseOrderExtParamsDto.setUserId(loginId);
        courseOrderExtParamsDto.setCourseIds(idsStr);
        courseOrderPayDto.setCourseOrderExtParamsDto(courseOrderExtParamsDto);
        // 消息生产者
        Message<CourseOrderPayDto> message = MessageBuilder.withPayload(courseOrderPayDto).build();
        rocketMQTemplate.sendMessageInTransaction("order-pay-group",
                "order-pay-topic:order-pay-tag",
                message,
                courseOrder);
        try {
            // 订单超时消息生产者
            SendResult syncSend = rocketMQTemplate.syncSend("pay-order-timeout-topic:pay-order-timeout-tag",
                    message,
                    2000,
                    4);
            if (!syncSend.getSendStatus().equals(SendStatus.SEND_OK)) {

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return orderNo;
    }

    /**
     * 添加订单详情
     *
     * @param courseOrder 订单详情
     */
    @Override
    public void insertOrderAndItem(CourseOrder courseOrder) {
        // 查询订单号
        CourseOrder orderNo = selectByOrderNo(courseOrder.getOrderNo());
        // 判断是否为空
        AssertUtil.isNull(orderNo, GlobelExceptionEnum.GLOBE_EXCEPTION_ENUM_PARAM_ERROR);
        // 订单提交
        insert(courseOrder);
        // 获取课程订单
        List<CourseOrderItem> courseOrderItems = courseOrder.getCourseOrderItems();
        // 循环设置订单ID
        courseOrderItems.forEach(e -> e.setOrderId(courseOrder.getId()));
        // 提交
        courseOrderItemService.insertBatch(courseOrderItems);
    }

    /**
     * 查询订单号
     *
     * @param orderNo
     * @return
     */
    @Override
    public CourseOrder selectByOrderNo(String orderNo) {
        Wrapper<CourseOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no", orderNo);
        CourseOrder courseOrder = selectOne(wrapper);
        return courseOrder;
    }
}
